#!/bin/sh

# Usage:
# To bootstrap your machine called mybox.com with piku
# 
# ./piku-bootstrap mybox.com

PBD=${PIKU_BOOTSTRAP_DIR:-~/.piku-bootstrap}
VENV="${PBD}/virtualenv"
REPO="${PBD}/piku"
VIRTUALENV_VERSION="16.0.0"
LOG="${PBD}/install.log"

main() {
  # print a message if this is a first time run
  if [ ! -d "${PBD}" ]; then
    echo "Looks like this is your first time running piku-bootstrap."
    echo "This script will self-install dependencies into ${PBD} now."
    echo "Hit enter to continue or ctrl-C to abort."
    read discarded
    echo
  fi

  # check git dependencies
  command -v git > /dev/null || bail "This script depends on git. Please install it to continue.";

  # ensure we have a dir
  mkdir -p "${PBD}"

  # ensure we have a virtualenv setup
  if [ ! -d "$VENV" ]; then
    echo " #> Virtualenv setup not found. Installing it into ${PBD}."
    ensure_virtualenv
  fi

  # get into virtualenv
  . "$VENV/bin/activate"

  # ensure we have the piku repo checked out
  if [ ! -d "${REPO}" ]; then
    echo " #> Piku repo not found. Installing it into ${REPO}."
    git clone https://github.com/piku/piku "${REPO}"
  fi

  # ensure ansible
  if [ "`command -v ansible-playbook`" = "" ]
  then
    echo " #> ansible-playbook binary not found. Installing it into ${PBD}."
    pip install -q "ansible==2.7.10" >"${LOG}" 2>&1 || bail "Failed to install Ansible.\nSee ${LOG} for details (you may be missing a C compiler)."
  fi

  if [ "$1" = "" ]
  then
    echo
    echo "Usage:"
    echo "       `basename $0` [USER@]HOST [PLAYBOOK] [ANSIBLE_ARGS...]"
    echo "       `basename $0` install-cli DESTINATION"
    echo "       `basename $0` list-playbooks"
    echo "       `basename $0` update"
    echo
    echo " HOST      Creates a user 'piku' on the machine 'HOST',"
    echo "           installs git, and sets up the piku.py script"
    echo "           by default, unless PLAYBOOK is specified."
    echo
    echo " USER      Optional non-root user to log in as (e.g. 'pi')."
    echo
    echo " PLAYBOOK  Optional playbook to deploy on to the server."
    echo "           For example 'nodeenv.yml' installs nodeenv."
    echo "           Can be an absolute path to your own playbook."
    echo
    echo " list-playbooks"
    echo "          List available built-in playbooks."
    echo
    echo " install-cli DESTINATION"
    echo "          Install the 'piku' CLI helper to e.g. ~/bin."
    echo
    echo " update   Pull the piku repo to get the latest playbooks."
    echo
    echo "Notes:"
    echo
    echo " * This script requires that you have root/sudo on HOST."
    echo " * Use \`ssh-copy-id USER@HOST\` to upload your SSH key first."
    echo " * HOST must be a Debian/Ubuntu based distribution."
    echo
    echo "Raspberry Pi example:"
    echo
    echo "\t`basename $0` pi@raspberrypi.local"
    echo
    echo " ** WARNING **"
    echo " This script installs software and makes changes on the target"
    echo " server. Only use a freshly provisioned server which you do not"
    echo " mind being modified and reconfigured."
    echo
  else
    case "$1" in
      update)
        echo "Updating piku repo."
        cd "${REPO}"
        git pull
        ;;
      first-run)
        echo
        echo " #> Success!"
        echo
        echo "The piku-bootstrap command is now installed in the current folder."
        echo "Copy it somewhere on your PATH, like ~/bin/ to make it accessible from anywhere."
        echo "Run 'piku-bootstrap install-cli DESTINATION' to install the piku helper."
        echo "Run 'piku-bootstrap' with no arguments for help."
        echo ""
        ;;
      install-cli)
        if [ "$2" = "" ]
        then
          echo "Usage: piku-bootstrap install-cli ~/bin"
        else
          ln -s "${REPO}/piku" "$2"
          echo "Installed piku cli to $2"
        fi
        ;;
      list-playbooks)
        ls "${REPO}/playbooks"
        ;;
      *)
        host="$1"; shift
        if [ ! "$1" = "" -a -z "${1##*.yml*}" ];
        then
          playbook="$1"; shift;
        else
          playbook="piku.yml"
        fi
        if [ -z "${playbook##*.yml*}" ]; then
          echo "Bootstrapping piku onto ${host}"
          builtin="${REPO}/playbooks/${playbook}"
          if [ ! -f "${playbook}" -a -f "${builtin}" ]; then
            echo "Using built-in playbook: ${playbook}"
            playbook="${builtin}"
          fi
          PYTHONWARNINGS="ignore" ansible-playbook -i "${host}", "${playbook}" "$@" --extra-vars "piku_user=$PIKU_USER"
        else
          echo "${playbook} is not a valid playbook name."
        fi
        ;;
    esac
  fi
}

bail_install() {
    echo " #> Self-installation failed."
    echo " #> Check ${LOG} for details."
    exit 1;
}

ensure_virtualenv() {
  # TODO: use local virtualenv instead if `command -v virtualenv` succeeds
  [ -d "${PBD}/virtualenv" ] || (\
      cd "${PBD}"
      [ -f "./.virtualenv-source/virtualenv.py" ] || install_virtualenv;
      echo " #> Setting up the virtual environment." && \
      ./.virtualenv-source/virtualenv.py -q "${PBD}/virtualenv" || bail_install)
      rm -rf ./.virtualenv-source
}

install_virtualenv() {
  VIRTUALENV_URL="https://pypi.io/packages/source/v/virtualenv/virtualenv-${VIRTUALENV_VERSION}.tar.gz"
  echo " #> Downloading & installing Virtualenv."
  rm -rf "./.virtualenv-source"
  mkdir -p "./.virtualenv-source"
  [ -f "./virtualenv.tar.gz" ] || curl -s -f -L -o "./virtualenv.tar.gz" "${VIRTUALENV_URL}" || bail_install
  tar -zxf "./virtualenv.tar.gz" -C "./.virtualenv-source/" --strip-components=1 && \
  [ -d "./.virtualenv-source" ] && (\
          cd "./.virtualenv-source" && \
          /usr/bin/env python setup.py build > ${LOG} 2>&1 ) \
          || bail_install;
}

bail() {
  echo "$@"
  exit 1;
}

main "$@"
